import { generate } from '@ant-design/colors';
import tinyColor from 'tinycolor2';
import classic from './classic';
import dependencies from './dependencies';
import defaultTheme from './default';

function pad2(num: number): string {
  let t = num.toString(16);
  if (t.length === 1) t = '0' + t;
  return t;
}

export function darken(colorStr: string, weight?: number): string {
  return mix('000', colorStr, weight);
}

export function mix(color1: string, color2: string, weight1?: number, alpha1?: number, alpha2?: number): string {
  const color1T = color1.replace('#', '');
  const color2T = color2.replace('#', '');
  const weight1T = weight1 || 0.5;
  const alpha1T = alpha1 || 1;
  const alpha2T = alpha2 || 1;

  const w = 2 * weight1T - 1;
  const alphaDelta = alpha1T - alpha2T;
  const w1 = ((w * alphaDelta === -1 ? w : (w + alphaDelta) / (1 + w * alphaDelta)) + 1) / 2;
  const w2 = 1 - w1;

  const nums1 = toNum3(color1T);
  const nums2 = toNum3(color2T);
  const r = Math.round(w1 * nums1[0] + w2 * nums2[0]);
  const g = Math.round(w1 * nums1[1] + w2 * nums2[1]);
  const b = Math.round(w1 * nums1[2] + w2 * nums2[2]);
  return '#' + pad2(r) + pad2(g) + pad2(b);
}

function toNum3(colorStr: string): number[] {
  const colorStrT =
    colorStr.length === 3
      ? colorStr[0] + colorStr[0] + colorStr[1] + colorStr[1] + colorStr[2] + colorStr[2]
      : colorStr;
  const r = parseInt(colorStrT.slice(0, 2), 16);
  const g = parseInt(colorStrT.slice(2, 4), 16);
  const b = parseInt(colorStrT.slice(4, 6), 16);
  return [r, g, b];
}

export function lighten(colorStr: string, weight?: number): string {
  return mix('fff', colorStr, weight);
}

export function fade(colorStr: string, alpha: number) {
  return tinyColor(colorStr).setAlpha(alpha).toRgbString();
}

export const extract = (cssStr: string, position: number): string => cssStr.split(' ')[position - 1];

const paletteColorsTemp = {};
export const palette = (colorStr: string, weight?: number): string => {
  if (paletteColorsTemp[`${colorStr}-${weight}`]) {
    return paletteColorsTemp[`${colorStr}-${weight}`];
  }
  const colorPalettes = generate(colorStr);
  colorPalettes.forEach((color, i) => {
    paletteColorsTemp[`${colorStr}-${i + 1}`] = color;
  });

  return paletteColorsTemp[`${colorStr}-${weight}`];
};

export const shade = darken;

export const tint = lighten;

export default {
  tinyColor,
  classic,
  dependencies,
  defaultTheme,
};
